<!-- tab组件: <me-tabs v-model="tabIndex" :tabs="tabs" @change="tabChange"></me-tabs> -->
<template>
  <view
    class="me-tabs"
    :class="['tabs-fixed', fixed]"
    :style="{
      height: tabHeightVal,
      top: topFixed,
      'margin-top': topMargin,
    }"
  >
    <scroll-view
      v-if="tabs.length"
      :id="viewId"
      :scroll-left="scrollLeft"
      scroll-x
      scroll-with-animation
      :scroll-animation-duration="300"
    >
      <view
        class="tabs-item"
        :class="['tabs-flex', !isScroll, 'tabs-scroll', isScroll]"
      >
        <!-- tab -->
        <view
          v-for="(tab, i) in tabs"
          :key="i"
          class="tab-item"
          :class="{ active: val === i }"
          :style="{
            color: val === i ? pitchColor : '',
            fontSize,
            width: tabWidthVal,
            height: tabHeightVal,
            'line-height': tabHeightVal,
          }"
          @click="tabClick(i)"
        >
          {{ getTabName(tab) }}
        </view>
        <!-- 下划线 -->
        <view class="tabs-line" :style="{ left: lineLeft }"></view>
      </view>
    </scroll-view>
  </view>
</template>
  
  <script setup lang="ts">
import {
  ref,
  computed,
  watchEffect,
  onMounted,
  onBeforeMount,
  getCurrentInstance,
} from "vue";
const { proxy } = getCurrentInstance() as any;

const props = withDefaults(
  defineProps<{
    pitchColor?: string;
    tabs?: Array<string | { name: string }>;
    nameKey?: string;
    value?: string | number;
    fixed?: boolean;
    tabWidth?: number;
    height?: number;
    top?: number;
    fontSize?: string;
  }>(),
  {
    pitchColor: "",
    tabs: () => [{ name: "全部" }, { name: "待付款" }],
    nameKey: "name",
    value: 0,
    fixed: false,
    tabWidth: undefined,
    height: 64,
    top: 0,
    fontSize: "28rpx",
  }
);

const emits = defineEmits(["update:value", "change"]);

const viewId = ref(`id_${Math.random().toString(36).substr(2, 16)}`);
const scrollLeft = ref(0);
const windowWidth = ref(0);
const windowTop = ref(0);
const val = ref(props.value as number);

const isScroll = computed(
  () => props.tabWidth !== undefined && props.tabs.length
);
const tabHeightPx = computed(() => uni.upx2px(props.height));
const tabHeightVal = computed(() => `${tabHeightPx.value}px`);
const tabWidthPx = computed(() => uni.upx2px(props.tabWidth ?? 0));
const tabWidthVal = computed(() =>
  isScroll.value ? `${tabWidthPx.value}px` : ""
);
const lineLeft = computed(() => {
  if (isScroll.value) {
    return `${tabWidthPx.value * val.value + tabWidthPx.value / 2}px`;
  } else {
    return `${
      (100 / props.tabs.length) * (val.value + 1) -
      100 / (props.tabs.length * 2)
    }%`;
  }
});
const topFixed = computed(() =>
  props.fixed ? `${windowTop.value + uni.upx2px(props.top)}px` : "0"
);
const topMargin = computed(() => (props.fixed ? "0" : `${props.top}rpx`));

const warpWidth = ref(0);

watchEffect(() => {
  initWarpRect(() => {
    scrollCenter();
  });
});

onBeforeMount(() => {
  const sys = uni.getSystemInfoSync();
  windowWidth.value = sys.windowWidth;
  windowTop.value = sys.windowTop;
  val.value = Number(props.value);
});

onMounted(() => {
  // 滚动到当前下标
  initWarpRect(() => {
    scrollCenter();
  });
});

function getTabName(tab: any) {
  return typeof tab === "object" ? tab[props.nameKey] : tab;
}

function tabClick(i: number) {
  if (val.value !== i) {
    emits("update:value", i);
    emits("change", i);
  }
  val.value = i;
}

function scrollCenter() {
  if (!isScroll.value) return;
  let tabLeft = tabWidthPx.value * val.value + tabWidthPx.value / 2;
  let diff = tabLeft - warpWidth.value / 2;
  scrollLeft.value = diff;
}

function initWarpRect(success: () => void) {
  setTimeout(() => {
    const query = uni.createSelectorQuery().in(proxy);
    query
      .select(`#${viewId.value}`)
      .boundingClientRect((rect: any) => {
        warpWidth.value = rect.width || windowWidth.value;
        success();
      })
      .exec();
  }, 20);
}
</script>

<style lang="scss">
.me-tabs {
  position: relative;
  font-size: 24rpx;
  background-color: #fff;
  // border-bottom: 1rpx solid #eee;
  box-sizing: border-box;
  overflow-y: hidden;
  background-color: #fff;
  &.tabs-fixed {
    z-index: 990;
    position: fixed;
    left: 0;
    width: 100%;
  }

  .tabs-item {
    position: relative;
    white-space: nowrap;
    padding-bottom: 30rpx; // 撑开高度,再配合me-tabs的overflow-y: hidden,以达到隐藏滚动条的目的
    box-sizing: border-box;
    .tab-item {
      position: relative;
      text-align: center;
      box-sizing: border-box;

      &.active {
        font-weight: bold;
        color: $uni-color-main;
      }
    }
  }

  // 平分的方式显示item
  .tabs-flex {
    display: flex;
    .tab-item {
      flex: 1;
    }
  }
  // 居左显示item,支持水平滑动
  .tabs-scroll {
    .tab-item {
      display: inline-block;
    }
  }

  // 选中tab的线
  .tabs-line {
    z-index: 1;
    position: absolute;
    bottom: 30rpx; // 至少与.tabs-item的padding-bottom一致,才能保证在底部边缘
    width: 50rpx;
    height: 6rpx;
    transform: translateX(-50%);
    border-radius: 4rpx;
    transition: left 0.3s;
    background: $uni-color-main;
  }
}
</style>
